package com.platform.core.web.controller;

import com.platform.aspect.WebLog;
import com.platform.comm.enums.YnEnum;
import com.platform.comm.jwt.JwtTokenUtil;
import com.platform.comm.jwt.TokenInfoUtil;
import com.platform.comm.util.WebIOUtil;
import com.platform.comm.validation.groups.Insert;
import com.platform.comm.validation.groups.Modify;
import com.platform.comm.web.results.DataJsonResult;
import com.platform.comm.web.results.JsonResult;
import com.platform.comm.web.results.PageListJsonResult;
import com.platform.core.entity.SysDepart;
import com.platform.core.security.auth.AuthenticationFacade;
import com.platform.core.service.SysDepartService;
import com.platform.core.service.SysUserRoleService;
import com.platform.dto.DepartNode;
import com.platform.dto.DepartQo;
import com.platform.dto.DomainTreeNode;
import com.platform.enums.CommFlagType;
import com.querydsl.core.BooleanBuilder;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;

/**
 * Description: 组织管理
 *
 * @author libin
 * Created on 2019/4/23
 **/
@RestController
@RequestMapping("management/depart")
public class SysDepartController extends BaseController {

    private final SysDepartService sysDepartService;
    private final SysUserRoleService sysUserRoleService;
    private final TokenInfoUtil tokenInfoUtil;

    public SysDepartController(SysDepartService sysDepartService, SysUserRoleService sysUserRoleService,
                               TokenInfoUtil tokenInfoUtil) {
        this.sysDepartService = sysDepartService;
        this.sysUserRoleService = sysUserRoleService;
        this.tokenInfoUtil = tokenInfoUtil;
    }

    @PostMapping(name = "新增组织信息", path = "create")
    @WebLog(theme = "新增[组织信息]", moduleName = "组织管理", type = WebLog.OpType.ADD, root = DepartQo.class)
    public JsonResult create(@Validated({Insert.class}) @RequestBody DepartQo departQo) {
        return createOrModifyWithResult(sysDepartService::create, departQo);
    }

    @PostMapping(name = "更新组织信息", path = "modify")
    @WebLog(theme = "更新[组织信息]", moduleName = "组织管理", type = WebLog.OpType.MOD, root = DepartQo.class)
    public JsonResult modify(@Validated({Modify.class}) @RequestBody DepartQo departQo) {
        return createOrModifyWithResult(sysDepartService::modify, departQo);
    }

    @PostMapping(name = "删除组织信息", path = "remove")
    @WebLog(theme = "删除[组织信息]", moduleName = "组织管理", type = WebLog.OpType.DEL, root = Map.class)
    public JsonResult remove(@RequestBody Map<String, String> map) {
        return removeOrOtherByIds(sysDepartService::remove, map.get("id"));
    }

    @PostMapping(name = "组织树查询", path = "searchDepartTree")
    public DataJsonResult<List<DepartQo>> searchDepartTree(@RequestBody Map<String, Object> map) {
        String departId = MapUtils.getString(map, "departId");
        String departCode = MapUtils.getString(map, "departCode");
        int level = MapUtils.getIntValue(map, "level");
        boolean ccf = MapUtils.getBoolean(map, "ccf", true);
        return DataJsonResult.succeed(sysDepartService.searchDepartTree(departId, departCode, level, ccf));
    }

    @PostMapping(name = "查询直接上级组织", path = "findParentDepart")
    public DataJsonResult<List<DepartQo>> findParentDepart(@RequestBody Map<String, Object> map) {
        String departId = MapUtils.getString(map, "departId");
        String departCode = MapUtils.getString(map, "departCode");
        boolean ccf = MapUtils.getBoolean(map, "ccf", false);
        return DataJsonResult.succeed(sysDepartService.searchDepartTree(departId, departCode, 1, ccf));
    }

    @PostMapping(name = "查询直接下级组织", path = "findChildrenDepart")
    public DataJsonResult<List<DepartQo>> findChildrenDepart(@RequestBody Map<String, Object> map) {
        String departId = MapUtils.getString(map, "departId");
        String departCode = MapUtils.getString(map, "departCode");
        boolean ccf = MapUtils.getBoolean(map, "ccf", false);
        return DataJsonResult.succeed(sysDepartService.searchDepartTree(departId, departCode, -1, ccf));
    }

    @PostMapping(name = "查询完整组织树", path = "findAllDepartTree")
    public DataJsonResult<List<DepartQo>> findAllDepartTree() {
        return DataJsonResult.succeed(sysDepartService.searchDepartTree(sysDepartService.getRootCode(), null, Integer.MIN_VALUE, true));
    }

    @PostMapping(name = "查询岗位组织树", path = "findPositionDepartTree")
    public DataJsonResult<List<DepartQo>> findPositionDepartTree() {
        return DataJsonResult.succeed(sysDepartService.findPositionDepartTree());
    }

    @PostMapping(name = "查询所有岗位信息", path = "findPosition")
    public DataJsonResult<List<SysDepart>> findPosition(@RequestBody Map<String, String> param) {
        return DataJsonResult.succeed(sysDepartService.findPosition(param.get("departId")));
    }

    /**
     * 废弃
     */
    @PostMapping(name = "批量删除组织信息", path = "batchRemove")
    @WebLog(theme = "批量删除[组织信息]", moduleName = "组织管理", type = WebLog.OpType.DEL_BATCH, root = Map.class)
    public JsonResult batchRemove(@RequestBody Map<String, Object> map) {
        List<String> ids = (List<String>) map.get("ids");
        return removeOrOtherByIds(sysDepartService::batchRemove, ids);
    }

    @PostMapping(name = "启用禁用组织", path = "/changeStatus")
    @WebLog(theme = "启用禁用[组织信息]", moduleName = "组织管理", type = WebLog.OpType.MOD, root = Map.class)
    public JsonResult changeStatus(@RequestBody Map<String, Object> map) {
        CommFlagType status = CommFlagType.getFlagByValue(map.get("status").toString());
        List<String> ids = (List<String>) map.get("ids");
        return change(sysDepartService::changeStatus, ids, status);
    }

    /**
     * 废弃
     */
    @PostMapping(name = "逻辑删除组织", path = "changeDelFlag")
    @WebLog(theme = "逻辑删除[组织信息]", moduleName = "组织管理", type = WebLog.OpType.DEL, root = Map.class)
    public JsonResult changeDelFlag(@RequestBody Map<String, Object> map) {
        YnEnum ynEnum = YnEnum.parse(map.get("yn").toString());
        List<String> ids = (List<String>) map.get("ids");
        return change(sysDepartService::changeDelFlag, ids, ynEnum);
    }

    @PostMapping(name = "分页查询组织信息", path = "search")
    public PageListJsonResult<DepartQo> search(@RequestBody Map<String, String> map) {
        MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
        map.forEach(parameters::add);
        return new PageListJsonResult<>(sysDepartService.queryDeparts(new BooleanBuilder(), getPageable(map), parameters, sysUserRoleService.checkAccessSubOrg()));
    }

    @PostMapping(name = "分页查询(供资源目录分配机构使用)", path = "searchInCatalog")
    public PageListJsonResult<DepartQo> searchInCatalog(@RequestBody Map<String, String> map) {
        return new PageListJsonResult<>(sysDepartService.queryDeparts(map, getPageable(map)));
    }

    @PostMapping(name = "组织树初始化", path = "tree")
    public DataJsonResult<List<DepartNode>> queryTree() {
        return query(sysDepartService::departTree,
                sysDepartService.getDepartById(AuthenticationFacade.getDepartId()),
                sysUserRoleService.checkAccessSubOrg());
    }

    @PostMapping(name = "获得区域树", path = "domainUserTree")
    public DataJsonResult<List<DomainTreeNode>> queryDomainUserTree(@RequestBody(required = false) Map<String, String> paramMap) {
        return query(sysDepartService::domainUserTree,
                sysDepartService.getDomainDepartCode("pre_ncloud_sys_depart_10000"),
                true, paramMap);
    }

    @PostMapping(name = "检查统一社会信用代码", path = "checkUnifiedCode")
    public DataJsonResult<Long> checkUnifiedCode(@RequestBody Map<String, String> map) {
        String id = map.get("id");
        String unifiedCode = map.get("unifiedCode");
        return query(sysDepartService::checkUnifiedCode, id, unifiedCode);
    }

    /**
     * 废弃
     */
    @PostMapping(name = "检查行政区划编码唯一性", path = "checkAreaCode")
    public DataJsonResult<Long> checkAreaCode(@RequestBody Map<String, String> map) {
        String id = map.get("id");
        String bizCode = map.get("bizCode");
        return query(sysDepartService::checkAreaCode, id, bizCode);
    }

    /**
     * 废弃
     */
    @PostMapping(name = "检查组织名称", path = "checkDepartName")
    public DataJsonResult<Long> checkDepartName(@RequestBody Map<String, String> map) {
        String id = map.get("id");
        String parentId = map.get("parentId");
        String departName = map.get("departName");

        return query(sysDepartService::checkDepartName, parentId, id, departName);
    }

    @PostMapping(name = "检查组织名称", path = "checkNameUnique")
    public DataJsonResult<Long> checkNameUnique(@RequestBody Map<String, String> requestBody) {
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        requestBody.forEach(params::add);
        return query(sysDepartService::checkNameUnique, params);
    }

    @PostMapping(name = "检查组织编码", path = "checkCodeUnique")
    public DataJsonResult<Long> checkCodeUnique(@RequestBody Map<String, String> requestBody) {
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        requestBody.forEach(params::add);
        return query(sysDepartService::checkCodeUnique, params);
    }

    @PostMapping(name = "同步组织到子系统", path = "syncSubsystem")
    public JsonResult syncSubsystem(@RequestBody Map<String, String> map) {
        String id = map.get("id");
        return removeOrOtherByIds(sysDepartService::syncSubsystem, id);
    }

    /**
     * 下载组织模板
     */
    @PostMapping(name = "下载组织模板", path = "/downloadDepartTemplate")
    public void downloadTemplate(HttpServletResponse response) throws IOException {
        InputStream tempFile = new ClassPathResource("templates/组织模板.xlsx").getInputStream();
        File targetFile = File.createTempFile("组织模板", ".xlsx");
        FileUtils.copyInputStreamToFile(tempFile, targetFile);
        Path path = Paths.get(targetFile.getPath());
        try {
            WebIOUtil.download(path, response, FilenameUtils.getName(path.toString()));
        } catch (IOException e) {
            throw new RuntimeException("下载模板文件失败", e);
        }
    }

    @PostMapping(name = "超级管理员查看区域组织树", path = "domainTree")
    public DataJsonResult<List<DomainTreeNode>> queryDomainTree() {
        return query(sysDepartService::leftDomainTree);
    }

    @PostMapping(name = "超级管理员查看组织信息", path = "searchPage")
    public PageListJsonResult<DepartQo> searchPage(@RequestBody Map<String, String> map) {
        MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
        map.forEach(parameters::add);
        return new PageListJsonResult<>(sysDepartService.searchPage(new BooleanBuilder(), getPageable(map), parameters));
    }

    @PostMapping(name = "根据组织父级id获取下一级子集组织", path = "children")
    public DataJsonResult<List<DepartNode>> children(@RequestBody Map<String, String> map) {
        String parentId = map.get("parentId");
        String status = map.get("status");
        String departKind = map.get("departKind");
        return query(sysDepartService::children, parentId, status, departKind);
    }

    @PostMapping(name = "根据当前用户获取根组织", path = "rootDepart")
    public DataJsonResult<List<DepartNode>> rootDepart(@RequestBody Map<String, String> map) {
        String status = map.get("status");
        String departKind = map.get("departKind");
        JwtTokenUtil.JwtUser jwtUser = tokenInfoUtil.getUser();
        return query(sysDepartService::rootDepart, sysDepartService.getDomainDepartCode(jwtUser.getDepartId()), status, departKind);
    }

    /**
     * 根据部门id获得部门信息
     *
     * @param departId ID
     * @return DepartNode 部门
     */
    @PostMapping(path = "queryDepartById")
    public DepartQo queryDepartById(String departId) {
        return sysDepartService.queryDepartById(departId);
    }

    /**
     * 根据部门id获得部门信息
     *
     * @param routeCode routeCode
     * @return DepartNode 部门
     */
    @PostMapping(path = "queryDepartByRouteCode")
    public DepartQo queryDepartByRouteCode(String routeCode) {
        return sysDepartService.findByDepartByRouteCode(routeCode);
    }


    @PostMapping(path = "queryDepartByUserId")
    public DepartQo queryDepartByUserId(String userId) {
        return sysDepartService.queryDepartByUserId(userId);
    }

    /**
     * 根据当前部门获取管理域下部门
     *
     * @param departId 当前部门ID
     * @return List
     */
    @PostMapping(path = "getDepartIdsWithDomainByCurrent")
    public List<String> getDepartIdsWithDomainByCurrent(String departId) {
        return sysDepartService.getDepartIdsWithDomainByCurrent(departId);
    }

    @PostMapping("findById")
    public DepartQo findById(String id) {
        return sysDepartService.findById(id);
    }

    @PostMapping("queryDepartByKind")
    public List<DepartQo> queryDepartByKind(@RequestBody Map<String, String> map) {
        return sysDepartService.queryDepartByKind(map.get("parentId"), map.get("departKind"), map.get("addSelf"));
    }

    @PostMapping("getChildDepartIdsById")
    public List<String> getChildDepartIdsById(String departId) {
        return sysDepartService.getChildDepartIdsById(departId);
    }

    @PostMapping("getDepartId")
    public List<String> getDepartId(@RequestBody Map<String, String> map) {
        return sysDepartService.getDepartId(map);
    }

    @PostMapping(name = "查询机构组织列表", path = "findNormalDepart")
    public List<DepartQo> findNormalDepart(@RequestBody Map<String, String> param) {
        return sysDepartService.findNormalDepart(param);
    }
}
